package doing;

import org.junit.Test;

import java.util.*;

import static com.study.util.LogUtil.info;
import static java.lang.Math.min;

/**
 * 120. Triangle 三角形最小路径和
 * <p>
 * 给定一个三角形，找出自顶向下的最小路径和。每一步只能移动到下一行中相邻的结点上。
 * 例如，给定三角形：
 * [
 * [2],
 * [3,4],
 * [6,5,7],
 * [4,1,8,3]
 * ]
 * 自顶向下的最小路径和为 11（即，2 + 3 + 5 + 1 = 11）。
 * <p>
 * 说明：
 * 如果你可以只使用 O(n) 的额外空间（n 为三角形的总行数）来解决这个问题，那么你的算法会很加分。
 * <p>
 * 2019-05-18 09:48
 **/
@SuppressWarnings("all")
public class Triangle {

    public int minimumTotal(List<List<Integer>> triangle) {
        if (triangle == null || triangle.size() == 0)
            return 0;

        // 加1可以不用初始化最后一层
        int[][] dp = new int[triangle.size() + 1][triangle.size() + 1];

        for (int i = triangle.size() - 1; i >= 0; i--) {
            List<Integer> curTr = triangle.get(i);
            for (int j = 0; j < curTr.size(); j++)
                dp[i][j] = min(dp[i + 1][j],
                        dp[i + 1][j + 1]) + curTr.get(j);
        }
        return dp[0][0];
    }

    @Test
    public void test() {
        info("11 -> {}", minimumTotal(new ArrayList() {{
            add(new ArrayList() {{
                addAll(new ArrayList() {{
                    add(2);
                }});
            }});
            add(new ArrayList() {{
                addAll(new ArrayList() {{
                    add(3);
                    add(4);
                }});
            }});
            add(new ArrayList() {{
                addAll(new ArrayList() {{
                    add(6);
                    add(5);
                    add(7);
                }});
            }});
            add(new ArrayList() {{
                addAll(new ArrayList() {{
                    add(4);
                    add(1);
                    add(8);
                    add(3);
                }});
            }});
        }}));
    }
}



























/*
// 解法1 二维数组进行求解
public int minimumTotal(List<List<Integer>> triangle) {
    if (triangle == null || triangle.size() == 0)
        return 0;

    // 加1可以不用初始化最后一层
    int[][] dp = new int[triangle.size()+1][triangle.size()+1];

    for (int i = triangle.size()-1; i>=0; i--) {
        List<Integer> curTr = triangle.get(i);
        for (int j = 0 ; j< curTr.size(); j++) {
            dp[i][j] = Math.min(dp[i+1][j], dp[i+1][j+1]) + curTr.get(j);
        }
    }
    return dp[0][0];
}

// 解法2 一维数组进行求解
public int minimumTotal(List<List<Integer>> triangle) {
    if (triangle == null || triangle.size() == 0){
        return 0;
    }
    // 只需要记录每一层的最小值即可
    int[] dp = new int[triangle.size()+1];

    for (int i = triangle.size() - 1; i >= 0; i--) {
        List<Integer> curTr = triangle.get(i);
        for (int j = 0; j < curTr.size(); j++) {
            //这里的dp[j] 使用的时候默认是上一层的，赋值之后变成当前层
            dp[j] = Math.min(dp[j],dp[j+1]) + curTr.get(j);
        }
    }
    return dp[0];
}
*/
